package com.atguigu.gulimall.product.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.atguigu.common.constant.ProductConstant;
import com.atguigu.common.to.SkuHasStockTo;
import com.atguigu.common.to.SkuReductionTo;
import com.atguigu.common.to.SpuBoundsTo;
import com.atguigu.common.to.elastic.Attrs;
import com.atguigu.common.to.elastic.SkuElasticModel;
import com.atguigu.common.utils.R;
import com.atguigu.gulimall.product.entity.*;
import com.atguigu.gulimall.product.feign.CounponFeignService;
import com.atguigu.gulimall.product.feign.SearchFeignService;
import com.atguigu.gulimall.product.feign.WareFeignService;
import com.atguigu.gulimall.product.service.*;
import com.atguigu.gulimall.product.vo.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.lang.ref.Reference;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.atguigu.common.utils.PageUtils;
import com.atguigu.common.utils.Query;

import com.atguigu.gulimall.product.dao.SpuInfoDao;
import org.springframework.transaction.annotation.Transactional;

@Slf4j
@Service("spuInfoService")
public class SpuInfoServiceImpl extends ServiceImpl<SpuInfoDao, SpuInfoEntity> implements SpuInfoService {

    @Autowired
    SpuInfoDescService spuInfoDescService;
    
    @Autowired
    SpuImagesService spuImagesService;
    
    @Autowired
    ProductAttrValueService productAttrValueService;
    
    @Autowired
    AttrService attrService;
    
    @Autowired
    SkuInfoService skuInfoService;
    
    @Autowired
    SkuImagesService skuImagesService;
    
    @Autowired
    SkuSaleAttrValueService skuSaleAttrValueService;
    
    @Autowired
    CounponFeignService counponFeignService;
    
    @Autowired
    BrandService brandService;
    
    @Autowired
    CategoryService categoryService;
    
    @Autowired
    WareFeignService wareFeignService;
    
    @Autowired
    SearchFeignService searchFeignService;
    
    
    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<SpuInfoEntity> page = this.page(
                new Query<SpuInfoEntity>().getPage(params),
                new QueryWrapper<SpuInfoEntity>()
        );

        return new PageUtils(page);
    }
    
    
    /** 
     * TODO 在保存中还存在其他问题，比如我们商品保存成功，但是积分没有保存成功情况
     * TODO 服务刚启动还处于不稳定状态情况
     * 保存Spu
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveSpuInfo(SpuSaveVo spuSaveVo) {
        //1、保存spu基本信息
        SpuInfoEntity spuInfoEntity = new SpuInfoEntity();
        BeanUtils.copyProperties(spuSaveVo, spuInfoEntity);
        spuInfoEntity.setCreateTime(new Date());
        spuInfoEntity.setUpdateTime(new Date());
        this.saveSpuBaseInfo(spuInfoEntity);
        //2、保存spu描述信息
        List<String> decript = spuSaveVo.getDecript();
        SpuInfoDescEntity spuInfoDescEntity = new SpuInfoDescEntity();
        spuInfoDescEntity.setDecript(String.join(",", decript));
        spuInfoDescEntity.setSpuId(spuInfoEntity.getId());
        spuInfoDescService.saveSpuInfoDesc(spuInfoDescEntity);
        //3、保存SpuImage
        List<SpuImagesEntity> spuImagesEntityList = spuSaveVo.getImages().stream().map(image -> {
            SpuImagesEntity spuImagesEntity = new SpuImagesEntity();
            spuImagesEntity.setSpuId(spuInfoEntity.getId());
            spuImagesEntity.setImgUrl(image);
            return spuImagesEntity;
        }).collect(Collectors.toList());
        spuImagesService.saveBatchSpuImage(spuImagesEntityList);
        //4、保存spu属性pms_product_attr_value
        List<BaseAttrs> baseAttrs = spuSaveVo.getBaseAttrs();
        List<ProductAttrValueEntity> attrValueEntities = baseAttrs.stream().map(item -> {
            ProductAttrValueEntity productAttrValue = new ProductAttrValueEntity();
            productAttrValue.setSpuId(spuInfoEntity.getId());
            productAttrValue.setAttrValue(item.getAttrValues());
            productAttrValue.setAttrId(item.getAttrId());
            productAttrValue.setQuickShow(item.getShowDesc());
            AttrEntity attrEntity = attrService.getById(item.getAttrId());
            if (attrEntity != null) {
                productAttrValue.setAttrName(attrEntity.getAttrName());
            }
            return productAttrValue;
        }).collect(Collectors.toList());
        productAttrValueService.saveProductAttr(attrValueEntities);
        
        //4.1、保存spu积分信息：sms-> sms_spu_bounds
        SpuBoundsTo spuBoundsTo = new SpuBoundsTo();
        BeanUtils.copyProperties(spuSaveVo.getBounds(), spuBoundsTo);
        try {
            R saveSpuBoundsResult = counponFeignService.save(spuBoundsTo);
            if (saveSpuBoundsResult.getCode() != 0) {
                log.error("远程保存spu基本信息失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("counponFeignService.save异常, 入参: {}, error: {}", spuBoundsTo.toString(), e.getMessage());
        }
        //5、保存sku基本信息
        //5.1、保存sku属性信息pms_sku_sale_attr_value
        List<Skus> skusList = spuSaveVo.getSkus();
        skusList.forEach(skus -> {
            String defaultImage = "";
            for (Images skusImage : skus.getImages()) {
                if (skusImage.getDefaultImg() == 1) {
                    defaultImage = skusImage.getImgUrl();
                }
            }
            //保存sku基本信息
            SkuInfoEntity skuInfoEntity = new SkuInfoEntity();
            BeanUtils.copyProperties(skus, skuInfoEntity);
            skuInfoEntity.setSpuId(spuInfoEntity.getId());
            skuInfoEntity.setCatalogId(spuInfoEntity.getCatalogId());
            skuInfoEntity.setBrandId(spuInfoEntity.getBrandId());
            skuInfoEntity.setSkuDefaultImg(defaultImage);
            skuInfoEntity.setSaleCount(0L);
            skuInfoService.saveSkuInfo(skuInfoEntity);
            //5.2  保存sku图片信息
            List<SkuImagesEntity> imagesEntityList = skus.getImages().stream().filter(images -> StringUtils.isNotEmpty(images.getImgUrl())).map(images -> {
                SkuImagesEntity skuImagesEntity = new SkuImagesEntity();
                BeanUtils.copyProperties(images, skuImagesEntity);
                skuImagesEntity.setSkuId(skuInfoEntity.getSkuId());
                return skuImagesEntity;
            }).collect(Collectors.toList());
            skuImagesService.saveBatchSkuImage(imagesEntityList);
            //5.3  保存sku销售属性
            List<Attr> skuAttr = skus.getAttr();
            List<SkuSaleAttrValueEntity> attrValueEntityList = skuAttr.stream().map(attr -> {
                SkuSaleAttrValueEntity saleAttrValue = new SkuSaleAttrValueEntity();
                BeanUtils.copyProperties(attr, saleAttrValue);
                saleAttrValue.setSkuId(skuInfoEntity.getSkuId());
                return saleAttrValue;
            }).collect(Collectors.toList());
            skuSaleAttrValueService.saveBatchSkuSaleAttrValue(attrValueEntityList);
            SkuReductionTo skuReductionTo = new SkuReductionTo();
            BeanUtils.copyProperties(skus, skuReductionTo);
            skuReductionTo.setSkuId(skuInfoEntity.getSkuId());
            if (skuReductionTo.getFullCount() > 0 || skuReductionTo.getFullPrice().compareTo(new BigDecimal("0")) == 1) {
                R saveSkuReductionResult = counponFeignService.saveInfo(skuReductionTo);
                if (saveSkuReductionResult.getCode() != 0) {
                    log.error("远程保存skuReduction失败！");
                }
            }
            //5.4  保存sku会员信息
            //5.5 保存sms->sms_sku_ladder sku优惠信息
            //5.6 保存sms -> sms_sku_full_reduction 满减信息
            //5.7 保存sms -> sms_member_price 会员价格
        });
        
    }
    
    /**
     * 保存Spu基本信息
     */
    @Override
    public void saveSpuBaseInfo(SpuInfoEntity spuInfoEntity) {
        this.save(spuInfoEntity);
    }
    
    
    @Override
    public PageUtils queryPageByCondition(Map<String, Object> params) {
        LambdaQueryWrapper<SpuInfoEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        String key = (String) params.get("key");
        if (StringUtils.isNotEmpty(key)) {
            lambdaQueryWrapper.and(query -> {
                query.eq(SpuInfoEntity::getId, key).or().likeRight(SpuInfoEntity::getSpuName, key);
            });
        }
        //status=0&key=&brandId=9&catelogId=225
        String status = (String) params.get("status");
        if (StringUtils.isNotEmpty(status)) {
            lambdaQueryWrapper.eq(SpuInfoEntity::getPublishStatus, status);
        }
    
        String brandId = (String) params.get("brandId");
        if (StringUtils.isNotEmpty(brandId) && !"0".equalsIgnoreCase(brandId)) {
            lambdaQueryWrapper.eq(SpuInfoEntity::getBrandId, brandId);
        }
    
        String catelogId = (String) params.get("catelogId");
        if (StringUtils.isNotEmpty(catelogId) && !"0".equalsIgnoreCase(catelogId)) {
            lambdaQueryWrapper.eq(SpuInfoEntity::getCatalogId, catelogId);
        }
        IPage<SpuInfoEntity> iPage = this.page(new Query<SpuInfoEntity>().getPage(params), lambdaQueryWrapper);
        return new PageUtils(iPage);
    }
    
    /**
     * 商品上架
     */
    @Override
    public void productUpper(Long spuId) {
    
        //查询除所有的skuinfo
        List<SkuInfoEntity> skuInfoEntityList = skuInfoService.getSkuInfoListBySpuId(spuId);
        if (CollectionUtils.isEmpty(skuInfoEntityList)) {
            return;
        }
        
        //查询销售属性和规格参数,并过滤出只允许搜索的数据
        List<Attrs> attrsList = null;
        List<ProductAttrValueEntity> attrValueEntities = productAttrValueService.baseAttrlistforspu(spuId);
        if (!CollectionUtils.isEmpty(attrValueEntities)) {
            List<Long> attrIds = attrValueEntities.stream().map(ProductAttrValueEntity::getAttrId).collect(Collectors.toList());
            List<Long> searchAttrList = attrService.selectSearchAttrIds(attrIds);
            Set<Long> searchAttrSet = new HashSet<>(searchAttrList);
            attrsList = attrValueEntities.stream()
                    .filter(value -> searchAttrSet.contains(value.getAttrId()))
                    .map(item -> {
                        Attrs attrs = new Attrs();
                        BeanUtils.copyProperties(item, attrs);
                        return attrs;
                    }).collect(Collectors.toList());
        }
        
        
        //查询库存
        List<Long> skuIds = skuInfoEntityList.stream().map(SkuInfoEntity::getSkuId).collect(Collectors.toList());
        List<SkuHasStockTo> skuHasStockToList = null;
        try {
            R skuHasStockResult = wareFeignService.getSkuHasStock(skuIds);
            if (skuHasStockResult.getCode() != 0) {
                return;
            }
            skuHasStockToList = skuHasStockResult.getData(new TypeReference<List<SkuHasStockTo>>(){});
        } catch (Exception e) {
            e.printStackTrace();
            log.error("wareFeignService.getSkuHasStock检验库存失败, 入参: [{}], error: {}", JSONObject.toJSONString(skuIds), e.getMessage());
        }
        Map<Long, SkuHasStockTo> stockToMap = null;
        if (!CollectionUtils.isEmpty(skuHasStockToList)) {
            stockToMap = skuHasStockToList.stream().collect(Collectors.toMap(SkuHasStockTo::getSkuId, item -> item));
        }
    
        List<Attrs> finalAttrsList = attrsList;
        Map<Long, SkuHasStockTo> finalStockToMap = stockToMap;
        List<SkuElasticModel> skuElasticModelList = skuInfoEntityList.stream().map(skuInfo -> {
            SkuElasticModel skuElasticModel = new SkuElasticModel();
            //skuDefaultImg,price
            //hasStock,hotScore,brandName,catalogName
            BeanUtils.copyProperties(skuInfo, skuElasticModel);
            skuElasticModel.setSkuPrice(skuInfo.getPrice());
            skuElasticModel.setSkuImg(skuInfo.getSkuDefaultImg());
            skuElasticModel.setHotScore(0L);
            //brandName,catalogName,brandImg
            BrandEntity brandEntity = brandService.getById(skuInfo.getBrandId());
            skuElasticModel.setBrandName(brandEntity.getName());
            skuElasticModel.setBrandImg(brandEntity.getLogo());
            CategoryEntity categoryEntity = categoryService.getById(skuInfo.getCatalogId());
            skuElasticModel.setCatalogName(categoryEntity.getName());
            //校验库存hasStock,hotScore,
            skuElasticModel.setHasStock(finalStockToMap == null ? true : finalStockToMap.get(skuInfo.getSkuId()).getHasStock());
            //设置规格参数与销售属性
            skuElasticModel.setAttrs(finalAttrsList);
            return skuElasticModel;
        }).collect(Collectors.toList());
        //封装es数据模型
    
        R product = null;
        try {
            product = searchFeignService.saveProduct(skuElasticModelList);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("saveProduct field, request parameters: [{}], error: {}", JSONObject.toJSONString(skuElasticModelList), e.getMessage());
        }
        if (product.getCode() == 0) {
            //更新spu状态
            baseMapper.updateSpuInfoStatus(spuId, ProductConstant.StatusEnum.UPPER_PRODUCT.getCode());
        }else {
            //重试与接口幂等行操作
        }
    
    }

    @Override
    public SpuInfoEntity getSpuInfoBySkuId(Long skuId) {
        SkuInfoEntity skuInfo = skuInfoService.getById(skuId);
        if (skuInfo == null) {
            return new SpuInfoEntity();
        }
        return getById(skuInfo.getSpuId());
    }


}